package com.coursehub.course.controller;

import com.coursehub.course.dto.MaterialDTO;
import com.coursehub.course.entity.Chapter;
import com.coursehub.course.entity.Course;
import com.coursehub.course.entity.Material;
import com.coursehub.course.service.MaterialService;
import com.coursehub.shared.dto.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.validation.constraints.NotBlank;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.Instant;
import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping("/api/materials")
@RequiredArgsConstructor
@Validated
public class MaterialController {
    
    private static final Logger log = LoggerFactory.getLogger(MaterialController.class);
    
    private final MaterialService materialService;
    
    /**
     * 保存文件到本地
     */
    private String saveFileToLocal(MultipartFile file, String materialName) throws IOException {
        String uploadDir = System.getProperty("user.dir") + File.separator + "uploads" + File.separator;
        File dir = new File(uploadDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        
        String filename = file.getOriginalFilename();
        String fullPath = uploadDir + filename;
        
        file.transferTo(new File(fullPath));
        log.info("文件上传路径: {}", fullPath);
        return fullPath;
    }
    
    /**
     * 上传资料
     */
    @PostMapping("/upload")
    public ResponseEntity<?> uploadMaterial(
            @RequestParam("file") MultipartFile file,
            @RequestParam("materialName") String materialName,
            @RequestParam("courseId") String courseId,
            @RequestParam("chapterId") String chapterId,
            @RequestParam(value = "materialLabel", required = false) String materialLabel
    ) {
        try {
            String path = saveFileToLocal(file, materialName);
            
            // 构造实体并保存数据库
            Material material = new Material();
            material.setMaterialId(UUID.randomUUID().toString());
            material.setMaterialName(file.getOriginalFilename());
            material.setMaterialPath(path);
            material.setUploadTime(Instant.now());
            material.setMaterialLabel(materialLabel);
            
            Course course = new Course();
            course.setCourseId(courseId);
            material.setCourse(course);
            
            Chapter chapter = new Chapter();
            chapter.setChapterId(chapterId);
            material.setChapter(chapter);
            
            materialService.uploadMaterial(material);
            
            log.info("资料上传成功: {}", material.getMaterialName());
            return ResponseEntity.ok("上传成功");
            
        } catch (IOException e) {
            log.error("文件上传失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("资料保存失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("资料保存失败: " + e.getMessage());
        }
    }
    
    /**
     * 根据课程ID和章节ID获取资料列表
     */
    @GetMapping("/{courseId}/chapter/{chapterId}")
    public ResponseEntity<List<MaterialDTO>> getMaterialsByCourseAndChapter(
            @PathVariable String courseId,
            @PathVariable String chapterId) {
        
        List<Material> materials = materialService.getMaterialsByCourseAndChapter(courseId, chapterId);
        
        List<MaterialDTO> materialDTOs = materials.stream().map(material -> {
            MaterialDTO dto = new MaterialDTO();
            dto.setMaterialId(material.getMaterialId());
            dto.setMaterialName(material.getMaterialName());
            dto.setMaterialPath(material.getMaterialPath());
            dto.setUploadTime(material.getUploadTime());
            dto.setMaterialLabel(material.getMaterialLabel());
            dto.setCourseId(material.getCourse().getCourseId());
            dto.setChapterId(material.getChapter().getChapterId());
            return dto;
        }).toList();
        
        return ResponseEntity.ok(materialDTOs);
    }
    
    /**
     * 根据课程ID获取资料列表
     */
    @GetMapping("/course/{courseId}")
    public ResponseEntity<List<Material>> getMaterialsByCourse(@PathVariable String courseId) {
        List<Material> materials = materialService.getMaterialByCourseId(courseId);
        return ResponseEntity.ok(materials);
    }
    
    /**
     * 根据章节ID获取资料列表
     */
    @GetMapping("/chapter/{chapterId}")
    public ResponseEntity<List<Material>> getMaterialsByChapter(@PathVariable String chapterId) {
        List<Material> materials = materialService.getMaterialByChapter(chapterId);
        return ResponseEntity.ok(materials);
    }
    
    /**
     * 根据资料ID获取资料详情
     */
    @GetMapping("/{materialId}")
    public ResponseEntity<Material> getMaterialById(@PathVariable String materialId) {
        return materialService.getMaterialById(materialId)
                .map(material -> ResponseEntity.ok(material))
                .orElse(ResponseEntity.notFound().build());
    }
    
    /**
     * 删除资料
     */
    @DeleteMapping("/{materialId}")
    public ResponseEntity<?> deleteMaterial(@PathVariable String materialId) {
        try {
            materialService.deleteMaterial(materialId);
            log.info("资料删除成功: {}", materialId);
            return ResponseEntity.ok("删除成功");
        } catch (Exception e) {
            log.error("资料删除失败: {}", materialId, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("删除失败: " + e.getMessage());
        }
    }
    
    /**
     * 下载资料
     */
    @GetMapping("/{materialId}/download")
    public ResponseEntity<Resource> downloadMaterial(@PathVariable String materialId) {
        try {
            Material material = materialService.getMaterialById(materialId)
                    .orElseThrow(() -> new RuntimeException("找不到资料"));
            
            File file = new File(material.getMaterialPath());
            if (!file.exists()) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
            }
            
            InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
            
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, 
                           "attachment; filename=" + URLEncoder.encode(material.getMaterialName(), "UTF-8"))
                    .contentLength(file.length())
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(resource);
                    
        } catch (Exception e) {
            log.error("文件下载失败: {}", materialId, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }
    
    /**
     * 验证资料是否存在
     */
    @GetMapping("/{materialId}/validate")
    public ResponseEntity<Boolean> validateMaterial(@PathVariable String materialId) {
        boolean exists = materialService.validateMaterial(materialId);
        return ResponseEntity.ok(exists);
    }
    
    /**
     * 根据课程ID获取资料ID列表
     */
    @GetMapping("/course/{courseId}/ids")
    public ResponseEntity<List<String>> getMaterialIdsByCourse(@PathVariable String courseId) {
        List<String> materialIds = materialService.getMaterialIdsByCourse(courseId);
        return ResponseEntity.ok(materialIds);
    }
    
    /**
     * 根据章节ID获取资料ID列表
     */
    @GetMapping("/chapter/{chapterId}/ids")
    public ResponseEntity<List<String>> getMaterialIdsByChapter(@PathVariable String chapterId) {
        List<String> materialIds = materialService.getMaterialIdsByChapter(chapterId);
        return ResponseEntity.ok(materialIds);
    }
    
    /**
     * 获取学生已学习的资料
     * 兼容单体系统API: GET /api/materials/student/{userId}/course/{courseId}/learned
     */
    @GetMapping("/student/{userId}/course/{courseId}/learned")
    public ResponseEntity<ApiResponse<List<Material>>> getLearnedMaterialsByStudent(
            @PathVariable @NotBlank(message = "用户ID不能为空") String userId,
            @PathVariable @NotBlank(message = "课程ID不能为空") String courseId) {
        log.info("获取学生已学习资料: userId={}, courseId={}", userId, courseId);
        List<Material> materials = materialService.getLearnedMaterialsByStudent(userId, courseId);
        return ResponseEntity.ok(ApiResponse.success(materials));
    }
    
    /**
     * 标记资料为已完成状态
     * 兼容单体系统API: POST /api/materials/student/{userId}/{materialId}/finish
     */
    @PostMapping("/student/{userId}/{materialId}/finish")
    public ResponseEntity<ApiResponse<Void>> markMaterialAsFinished(
            @PathVariable @NotBlank(message = "用户ID不能为空") String userId,
            @PathVariable @NotBlank(message = "资料ID不能为空") String materialId) {
        log.info("标记资料完成: userId={}, materialId={}", userId, materialId);
        materialService.markMaterialAsFinished(userId, materialId);
        return ResponseEntity.ok(ApiResponse.success("资料标记完成成功"));
    }
}